#ifndef _I_COMPONENT_H
#define _I_COMPONENT_H

#include "..\Math\Vector2.h"
#include "..\Generic\GameTime.h"
#include <string>
#include <vector>
#include <map>
#include <functional>

class GameObjectManager;
class IComponent;
class GameObject
{
public:	
	//GameObject() : m_name("New GameObject") {};

	GameObject(const std::string& p_name, GameObjectManager* p_gameObjectManager, std::function<void()> p_cTorCallBack = nullptr) : m_name(p_name), m_gameObjectManager(p_gameObjectManager),
		m_cTorCallBack(p_cTorCallBack), m_dTorCallBack(nullptr) { if(m_cTorCallBack != nullptr) { m_cTorCallBack(); } };

	GameObject(std::function<void()> p_cTorCallBack = nullptr) : m_cTorCallBack(p_cTorCallBack) { if (m_cTorCallBack != nullptr) m_cTorCallBack(); }
	virtual ~GameObject() 
	{ 
		clearComponents(); if(m_dTorCallBack != nullptr) { m_dTorCallBack(); } 
	};

	const std::string& getName() { return m_name; };
	void setName(const std::string& p_name) { m_name = p_name; };

	void initComponents();	

	void addComponent(IComponent* p_component);

	IComponent* getComponent(const std::string& p_type);
	IComponent* getComponent(const std::string& p_type, unsigned int p_index);
	
	void removeComponent(IComponent* p_component);
	void removeComponents(const std::string& p_type);
	void clearComponents();
	void update(const GameTime& p_gameTime);
	void setGameObjectManager(GameObjectManager* p_gameObjectManager) { m_gameObjectManager = p_gameObjectManager; }
	void setDTorCallBack(std::function<void()> p_setDTorCallBack) { m_dTorCallBack = p_setDTorCallBack; }
	void removeMe();

	GameObjectManager* getGameObjectManager() const { return m_gameObjectManager; }
	
	void setPosition(float p_x, float p_y) { m_position.x = p_x; m_position.y = p_y; }
	void setPosition(const vn::Vector2& p_position) { m_position = p_position; }

	const vn::Vector2& getPosition() { return m_position; }

private:
	void remove(IComponent* p_component);

	typedef std::vector< IComponent* > ComponentList;
	typedef std::map< std::string, ComponentList* > ComponentMap;

	void addInternal(IComponent* pComponent, const std::string& p_type);
	void removeInternal(IComponent* pComponent, const std::string& p_type);

	ComponentMap m_components;
	std::string m_name;
	GameObjectManager* m_gameObjectManager;
	std::function<void()> m_cTorCallBack;
	std::function<void()> m_dTorCallBack;
	std::vector<IComponent*> m_removeList;

	vn::Vector2 m_position;
};



#endif //I_COMPONENT_H